﻿using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.IdentityFramework;
using Abp.Localization;
using Abp.Organizations;
using Abp.Runtime.Caching;
using Abp.Runtime.Session;
using Abp.UI;
using Microsoft.AspNet.Identity;
using Pay.WxPay;
using SingleUserMall.Authorization.Roles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SingleUserMall.Authorization.Users
{
    public class UserManager : AbpUserManager<Role, User>
    {
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly IRepository<User, long> _userRepository;
        private readonly IRepository<UserCash, long> _userCashRepository;
        private readonly IRepository<UserCode, long> _userCodeRepository;
        public UserManager(
            UserStore userStore,
            RoleManager roleManager,
            IPermissionManager permissionManager,
            IUnitOfWorkManager unitOfWorkManager,
            ICacheManager cacheManager,
            IRepository<OrganizationUnit, long> organizationUnitRepository,
            IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
            IOrganizationUnitSettings organizationUnitSettings,
            ILocalizationManager localizationManager,
            ISettingManager settingManager,
            IdentityEmailMessageService emailService,
            IUserTokenProviderAccessor userTokenProviderAccessor,
            IRepository<User, long> userRepository,
            IRepository<UserCash, long> userCashRepository,
            IRepository<UserCode, long> userCodeRepository)
            : base(
                  userStore,
                  roleManager,
                  permissionManager,
                  unitOfWorkManager,
                  cacheManager,
                  organizationUnitRepository,
                  userOrganizationUnitRepository,
                  organizationUnitSettings,
                  localizationManager,
                  emailService,
                  settingManager,
                  userTokenProviderAccessor)
        {
            _unitOfWorkManager = unitOfWorkManager;
            _userRepository = userRepository;
            _userCashRepository = userCashRepository;
            _userCodeRepository = userCodeRepository;
        }

        public async Task<User> FindUserWithOpenIdAsync(string openId)
        {
            var user = await _userRepository.FirstOrDefaultAsync(x => x.OpenId == openId);
            return user;
        }

        public List<User> FindUsersByIds(string[] Ids)
        {
            return _userRepository.GetAll().Where(x => Ids.Contains(x.Id.ToString())).ToList();
        }

        public async Task SetCode(string phoneNumber, string smsCode)
        {
            await _userCodeRepository.InsertAsync(new UserCode
            {
                PhoneNumber = phoneNumber,
                SmsCode = smsCode
            });
        }

        public async Task<bool> CheckCode(string phoneNumber, string smsCode)
        {
            var last = _userCodeRepository.GetAll().Where(x => x.PhoneNumber == phoneNumber)
                .OrderByDescending(x => x.CreationTime).FirstOrDefault();
            var result = last != null && last.SmsCode == smsCode;
            return await Task.FromResult(result);
        }

        public async Task<bool> CheckCanSendCode(string phoneNumber, double? checkDay)
        {
            if(checkDay == null) return await Task.FromResult(true);
            var last = _userCodeRepository.GetAll().Where(x => x.PhoneNumber == phoneNumber)
                .OrderByDescending(x => x.CreationTime).FirstOrDefault();
            var result = last == null || last.CreationTime.AddDays(checkDay.Value) < DateTime.Now;
            return await Task.FromResult(result);
        }

        //检查是否是超级管理员
        public async Task<bool> CheckAdminAndPlatformRole(long userId)
        {
            var user = await _userRepository.FirstOrDefaultAsync(x => x.Id == userId);
            var role = user.Roles.FirstOrDefault(x => x.RoleId == 1 || x.RoleId == 11);
            return role!=null ? true : false;
        }


        public async Task<User> FindUserWithPhoneAsync(string phone)
        {
            var user = await _userRepository.FirstOrDefaultAsync(x => x.PhoneNumber == phone);
            return user;
        }

        public void Cash(UserCash userCash)
        {
            try
            {
                var user = _userRepository.FirstOrDefault(userCash.UserId);
                if (userCash.Status == CashStatus.Init)
                {
                    if(userCash.CashType == CashType.Commision)
                    {
                        if (user.Commision >= userCash.Amount)
                        {
                            WxPayContext.H5Instance.PayBank(userCash.OrderNo, userCash.CardNumber, userCash.CardName, userCash.BankCode, userCash.Amount);
                            userCash.Status = CashStatus.Processing;
                            user.Commision = user.Commision - userCash.Amount;
                        }
                        else
                        {
                            throw new UserFriendlyException("个人佣金金额不够");
                        }
                    }
                    else if(userCash.CashType == CashType.RedPacket)
                    {
                        if (user.UserRedPacket >= userCash.Amount)
                        {
                            WxPayContext.H5Instance.PayBank(userCash.OrderNo, userCash.CardNumber, userCash.CardName, userCash.BankCode, userCash.Amount);
                            userCash.Status = CashStatus.Processing;
                            user.UserRedPacket = user.UserRedPacket - userCash.Amount;
                        }
                        else
                        {
                            throw new UserFriendlyException("个人红包金额不够");
                        }
                    }
                    else if (userCash.CashType == CashType.CanUsePoint)
                    {
                        if (user.CanUsePoints >= userCash.Amount)
                        {
                            WxPayContext.H5Instance.PayBank(userCash.OrderNo, userCash.CardNumber, userCash.CardName, userCash.BankCode, userCash.Amount);
                            userCash.Status = CashStatus.Processing;
                            user.CanUsePoints = user.CanUsePoints - userCash.Amount;
                        }
                        else
                        {
                            throw new UserFriendlyException("个人可提现体验金不够");
                        }
                    }
                }
                else
                {
                    WxPayContext.H5Instance.PayBank(userCash.OrderNo, userCash.CardNumber, userCash.CardName, userCash.BankCode, userCash.Amount);
                    userCash.Status = CashStatus.Processing;
                }
            }
            catch (Exception ex)
            {
                throw new UserFriendlyException(ex.Message);
            }
        }

        [UnitOfWork(false)]
        public void CashResultQuery()
        {
            var userCashes = _userCashRepository.GetAll().Where(x => x.Status == CashStatus.Processing).OrderBy(x => x.CreationTime).ToList();
            userCashes.ForEach(x =>
            {
                try
                {
                    var status = WxPayContext.H5Instance.PayBalanceResult(x.OrderNo);
                    x.Status = status;
                    if (status == CashStatus.Success)
                    {
                        x.ErrorMessage = null;
                    }
                }
                catch (Exception ex)
                {
                    x.ErrorMessage = ex.Message;
                }
                _unitOfWorkManager.Current.SaveChanges();
            });
        }
    }
}